Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support checks in relay modules #19639

Open
wants to merge 8 commits into
base: master
Choose a base branch
from

Conversation

zeroSteiner
Copy link
Contributor

We now have two relay modules with more on the horizon. This PR adds the ability for our users to check targets for viability in the context of the modules. In the case of SMB, this checks the target has SMB signing disabled. In the case of ESC8, it checks that the target URI responds with a 401 and offers NTLM as an authentication mechanism.

Adding the check method required changes to how the modules operate. They had originally used the RELAY_TARGETS datastore option to avoid the framework splitting RHOSTS into individual RHOST options as it does for other modules types (except those that are scanners or do not register the RHOSTS option). In order for the check command to work, the RHOSTS needed to be registered, so the target to check is available to the module. For the actual exploitation though, the RHOSTS value needed to be kept as it is (e.g. a list of IP addresses, CIDR range, etc.). To support this, I added a new MultipleTargetHosts mixin that is checked for in the run command dispatcher when an Auxiliary or Exploit module is run. This check is included where the previous Scanner mixin check was included and where the datastore is checked for containing RHOSTS. With this in place, the relay modules can now uses the RHOSTS datastore option and iterate over the targets itself, while also having a check_host method that can return a check code for individual hosts. This ensures the option works consistently when the RHOSTS datastore option is set or a range is specified as an argument to the check command.

Because of where the RHOSTS string is split into individual target hosts, the MultipleTargetHosts mixin is incompatible with the AutoCheck mixin. The issue here is that the run method has the RHOSTS string without having been split and the AutoCheck mixin is incapable of splitting it and checking each host individually for exploitability. This would also introduce an ambiguity for how a case where a group of N hosts are defined and N-1 are vulnerable. Presumably, the module should fail, but it's not well equipped to report the vulnerability status of each individual host as the check command is. This seems like a reasonable limitation at this time and something that can be left alone for the time being.

Testing

  • Use the auxiliary/server/relay/esc8 module
    • Set the RHOSTS option to multiple targets
    • Run the check command with no arguments, see it pulled the hosts to test from the RHOSTS datastore option
    • Run the check command with a target host argument (e.g. check 192.168.159.10-11) and see that it pulled the hosts to test from the argument
    • See that the module still works as intended
  • Use the exploit/windows/smb/smb_relay module
    • Set the RHOSTS option to multiple targets
    • Run the check command with no arguments, see it pulled the hosts to test from the RHOSTS datastore option
    • Run the check command with a target host argument (e.g. check 192.168.159.10-11) and see that it pulled the hosts to test from the argument
    • See that the module still works as intended

Example

ESC8 checking:

metasploit-framework.pr (S:0 J:0) auxiliary(server/relay/esc8) > check 192.168.159.10-11
[*] 192.168.159.10:80 - The target appears to be vulnerable. Server replied that authentication is required and NTLM is supported.

[-] The host (192.168.159.11:80) was unreachable.
[*] 192.168.159.11:80 - Cannot reliably check exploitability.
metasploit-framework.pr (S:0 J:0) auxiliary(server/relay/esc8) >

SMB relay checking:

metasploit-framework.pr (S:0 J:0) exploit(windows/smb/smb_relay) > check 192.168.159.10-11
[+] 192.168.159.10 - The target is vulnerable. Signing is not required by the target server.
[*] 192.168.159.11 - Cannot reliably check exploitability. Failed to connect and negotiate an SMB connection.
metasploit-framework.pr (S:0 J:0) exploit(windows/smb/smb_relay) >

@@ -209,11 +209,22 @@ def print_prefix
# Otherwise we are logging in the global context where rhost can be any
# size (being an alias for rhosts), which is not very useful to insert into
# a single log line.
if rhost && rhost.split(' ').length == 1
Copy link
Contributor Author

@zeroSteiner zeroSteiner Nov 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check for a space does not account for all of the different ways RangeWalker can handle multiple hosts. Instead, we should actually use RangeWalker to count how many hosts were targeted and only report it if there's a single target. Because this calculation is too expensive to run each time a message is printed, we cache the value.

The comment implies that this was always the intention.

target_host = nil
unless m.target_host.blank?
# only propagate the target_host value if it's exactly 1 host
if (rw = Rex::Socket::RangeWalker.new(m.target_host)).length == 1
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because RHOSTS wasn't being split any more, RHOST was still a range. This caused Rex::Socket.getaddress to raise a resolution error. Instead we use RangeWalker again to count how many hosts were being target and only propagate the address if it's exactly one. This also fixes an issues in the previous implementation where if a hostname resolved to multiple addresses, the wrong one may have been selected and copied to #target_host. This avoids that by only copying when we're confident that the target is correct because it's a single value.

@zeroSteiner zeroSteiner marked this pull request as ready for review November 12, 2024 18:50
@bwatters-r7 bwatters-r7 self-assigned this Nov 12, 2024
@bwatters-r7
Copy link
Contributor

bwatters-r7 commented Nov 22, 2024

Almost everything looks right, but I'm seeing that the psexec from relay is failing, despite full authentication as Domain Admin.
This behavior is shared with master, so it is not a regression and not blocking.

[+] Identity: EXAMPLE\Administrator - Successfully authenticated against relay target smb://10.5.132.182:445
[SMB] NTLMv2-SSP Client     : 10.5.132.182
[SMB] NTLMv2-SSP Username   : EXAMPLE\Administrator
[SMB] NTLMv2-SSP Hash       : Administrator::EXAMPLE:079f5ab963313aca:92293435dd6a03d6bad87cffb3cceaad:01010000000000003590a56dfb3cdb0110adea21f20d79a00000000002000e004500580041004d0050004c00450001001e00570049004e002d00440052004300390048004300440049004d0041005400040016006500780061006d0070006c0065002e0063006f006d0003003600570049004e002d00440052004300390048004300440049004d00410054002e006500780061006d0070006c0065002e0063006f006d00050016006500780061006d0070006c0065002e0063006f006d00070008003590a56dfb3cdb0106000400020000000800300030000000000000000100000000200000ed167b4f6270d072cfe535a4835f2ad50c97dc0c4e4f2e7e326e2acbb4766f670a001000000000000000000000000000000000000900220063006900660073002f00310030002e0035002e003100330035002e003200300031000000000000000000

[*] 10.5.132.182:445 - Running psexec
D, [2024-11-22T10:27:31.149237 #3457] DEBUG -- : Dispatching request to do_tree_connect_smb2 (session: #<Session id: 965129682, user_id: "EXAMPLE\\Administrator", state: :valid>)
[*] Received request for EXAMPLE\Administrator
[-] Failed running psexec against target  - RubySMB::Error::UnexpectedStatusCode The server responded with an unexpected status code: STATUS_ACCESS_DENIED

#19673

@smcintyre-r7 smcintyre-r7 added blocked Blocked by one or more additional tasks enhancement rn-enhancement release notes enhancement labels Nov 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
blocked Blocked by one or more additional tasks enhancement rn-enhancement release notes enhancement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants